package com.hethongviet.job.pages;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.lang.reflect.Method;
import java.util.List;

import com.hethongviet.job.AppMain;
import com.hethongviet.job.R;
import com.hethongviet.job.helpers.CodeResult;
import com.hethongviet.job.models.FileImage;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.BitmapFactory.Options;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.SensorManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore.Images.Media;
import android.view.Display;
import android.view.KeyEvent;
import android.view.OrientationEventListener;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;

@SuppressLint("NewApi")
public class CameraActivity extends Activity implements SurfaceHolder.Callback,
		OnClickListener
{

	private Camera _camera = null;
	private boolean _previewRunning = false;

	private OrientationEventListener _orientationEventListener;
	private int _orientation = -1;

	private static final int ORIENTATION_PORTRAIT_NORMAL = 1;
	private static final int ORIENTATION_PORTRAIT_INVERTED = 2;
	private static final int ORIENTATION_LANDSCAPE_NORMAL = 3;
	private static final int ORIENTATION_LANDSCAPE_INVERTED = 4;

	// private static final int IMAGE_COMPRESS_RATIO = 75;

	Camera.PictureCallback _pictureCallback = new PictureCallback() {
		public void onPictureTaken(byte[] data, Camera camera)
		{
			if (data != null)
			{
				Intent intent = new Intent();
				boolean isSuccess = true;

				BitmapFactory.Options options = new Options();
				options.inSampleSize = 5;
				Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);

				ContentValues image = new ContentValues();
				// additional picture meta-data
				// image.put(Media.DISPLAY_NAME, AppMain.IMAGE_FILE_NAME);
				// image.put(Media.MIME_TYPE, "image/jpg");
				// image.put(Media.TITLE, "");
				// image.put(Media.DESCRIPTION, "");
				// image.put(Media.DATE_ADDED, "");
				// image.put(Media.DATE_TAKEN, "");
				// image.put(Media.DATE_MODIFIED, "");

				// do not rotate image, just put rotation info in
				switch (_orientation)
				{
					case ORIENTATION_PORTRAIT_NORMAL:
						image.put(Media.ORIENTATION, 180);
						break;
					case ORIENTATION_LANDSCAPE_NORMAL:
						image.put(Media.ORIENTATION, 90);
						break;
					case ORIENTATION_PORTRAIT_INVERTED:
						// default:
						image.put(Media.ORIENTATION, 0);
						break;
					case ORIENTATION_LANDSCAPE_INVERTED:
						image.put(Media.ORIENTATION, 270);
						break;
				}

				// // store the picture
				// Uri uri = getContentResolver().insert(
				// Media.EXTERNAL_CONTENT_URI, image);
				// Bitmap bitmap = null;
				// try
				// {
				// bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
				// OutputStream out = getContentResolver().openOutputStream(
				// uri);
				// isSuccess = bitmap.compress(Bitmap.CompressFormat.JPEG,
				// IMAGE_COMPRESS_RATIO, out);
				// out.close();
				// intent.setData(uri);
				//
				// } catch (Exception e)
				// {
				// e.printStackTrace();
				// isSuccess = false;
				// }

				int degree = image.getAsInteger(Media.ORIENTATION);
				Matrix matrix = new Matrix();
				matrix.postRotate(degree);

				bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
				if (isSuccess)
				{
					String path= Environment.getExternalStorageDirectory() + AppMain.DIRECTORY_DATA_SAVE;
					
					try
					{
						FileOutputStream fileOutputStream = new FileOutputStream(path + "/" + AppMain.IMAGE_FILE_NAME_DEFAULT);
						bitmap.compress(CompressFormat.JPEG, 100, fileOutputStream);
					} catch (FileNotFoundException e)
					{
						e.printStackTrace();
					}
					
					AppMain._imageFileView = new FileImage(bitmap, AppMain.IMAGE_FILE_NAME_DEFAULT, AppMain.IMAGE_FILE_NAME_DEFAULT, path);
					_camera.startPreview();
					setResult(RESULT_OK, intent);
				}
				else setResult(RESULT_CANCELED, intent);
				finish();
			}
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		getWindow().setFormat(PixelFormat.TRANSLUCENT);
		AppMain.prepareWindow(this);
		// force Landscape layout
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
				| ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

		setContentView(R.layout.page_camera);

		SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
		surfaceView.setOnClickListener(this);
		SurfaceHolder surfaceHolder = surfaceView.getHolder();
		surfaceHolder.addCallback(this);
		surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		AppMain.showMessageBox(this, getString(R.string.textMessageTouchOnScreen));
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event)
	{
		if (keyCode == KeyEvent.KEYCODE_CAMERA)
		{
			_camera.takePicture(null, _pictureCallback, _pictureCallback);
			return true;
		}
		else return super.onKeyDown(keyCode, event);
	}

	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height)
	{
		if (_camera == null)
		{
			AppMain._codeResultService = CodeResult.FAIL_OPEN_CAMERA;
			onWindowFocusChanged(true);
			return;
		}
		if (_previewRunning) _camera.stopPreview();
		Camera.Parameters parameters = _camera.getParameters();
		// parameters.setPictureSize(width, height); error: with phones do not
		// support
		List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
		/*
		 * if (sizes != null && sizes.size() > 0) { int screenWidth =
		 * getWindowManager().getDefaultDisplay().getWidth(); int screenHeight =
		 * getWindowManager().getDefaultDisplay().getHeight(); int previewWidth
		 * = sizes.get(0).width; int previewHeight = sizes.get(0).height; if
		 * (screenWidth > screenHeight) { if (previewWidth > previewHeight)
		 * parameters.setPreviewSize( previewWidth, previewHeight); else
		 * parameters.setPreviewSize(previewHeight, previewWidth); } else { if
		 * (previewWidth < previewHeight) parameters.setPreviewSize(
		 * previewWidth, previewHeight); else
		 * parameters.setPreviewSize(previewHeight, previewWidth); } } else
		 * parameters.setPictureSize(width, height);
		 */
		int previewWidth = sizes.get(0).width;
		int previewHeight = sizes.get(0).height;
		parameters.setPreviewSize(previewWidth, previewHeight);

		if (Integer.parseInt(Build.VERSION.SDK) >= 8) setDisplayOrientation(_camera, 90);
		else
		{
			if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
			{
				parameters.set("orientation", "portrait");
				parameters.set("rotation", 90);
			}
			if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
			{
				parameters.set("orientation", "landscape");
				parameters.set("rotation", 90);
			}
		}
		_camera.setParameters(parameters);
		try
		{
			_camera.setPreviewDisplay(holder);
		} catch (Exception e)
		{
			e.printStackTrace();
		}
		_camera.startPreview();
		_previewRunning = true;
	}

	protected void setDisplayOrientation(Camera camera, int angle)
	{
		Method downPolymorphic;
		try
		{
			downPolymorphic = camera.getClass().getMethod("setDisplayOrientation", new Class[] { int.class });
			if (downPolymorphic != null) downPolymorphic.invoke(camera, new Object[] { angle });
		} catch (Exception e1)
		{
			e1.printStackTrace();
		}
	}

	public void surfaceCreated(SurfaceHolder holder)
	{
		try
		{
			_camera = Camera.open();
		} catch (RuntimeException e)
		{
			e.printStackTrace();
			AppMain._codeResultService = CodeResult.FAIL_OPEN_CAMERA;
			onWindowFocusChanged(true);
		}
	}

	public void surfaceDestroyed(SurfaceHolder holder)
	{
		if (_camera == null)
		{
			AppMain._codeResultService = CodeResult.FAIL_OPEN_CAMERA;
			onWindowFocusChanged(true);			
		}
		else
		{
			_camera.stopPreview();
			_previewRunning = false;
			_camera.release();
		}
	}

	public void onClick(View v)
	{

		_camera.takePicture(null, _pictureCallback, _pictureCallback);
	}

	// do not run ..
	// @Override
	// public boolean onTouchEvent(MotionEvent event)
	// {
	// _camera.takePicture(null, _pictureCallback, _pictureCallback);
	// return true;
	// }

	@Override
	protected void onResume()
	{
		super.onResume();
		if (_orientationEventListener == null)
		{
			_orientationEventListener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) {

				@Override
				public void onOrientationChanged(int orientation)
				{

					// determine our orientation based on sensor response
					int lastOrientation = _orientation;

					Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();

					if (display.getOrientation() == Surface.ROTATION_0)
					{ // landscape oriented devices
						if (orientation >= 315 || orientation < 45)// 0
						{
							if (_orientation != ORIENTATION_LANDSCAPE_NORMAL)
							{
								_orientation = ORIENTATION_LANDSCAPE_NORMAL;
							}
						}
						else if (orientation < 315 && orientation >= 225)// 270
						{
							if (_orientation != ORIENTATION_PORTRAIT_INVERTED)
							{
								_orientation = ORIENTATION_PORTRAIT_INVERTED;
							}
						}
						else if (orientation < 225 && orientation >= 135)// 180
						{
							if (_orientation != ORIENTATION_LANDSCAPE_INVERTED)
							{
								_orientation = ORIENTATION_LANDSCAPE_INVERTED;
							}
						}
						else if (orientation < 135 && orientation > 45)// 90
						{
							if (_orientation != ORIENTATION_PORTRAIT_NORMAL)
							{
								_orientation = ORIENTATION_PORTRAIT_NORMAL;
							}
						}
					}
					else
					{ // portrait oriented devices
						if (orientation >= 315 || orientation < 45)// 0
						{
							if (_orientation != ORIENTATION_PORTRAIT_NORMAL)
							{
								_orientation = ORIENTATION_PORTRAIT_NORMAL;
							}
						}
						else if (orientation < 315 && orientation >= 225)// 270
						{
							if (_orientation != ORIENTATION_LANDSCAPE_NORMAL)
							{
								_orientation = ORIENTATION_LANDSCAPE_NORMAL;
							}
						}
						else if (orientation < 225 && orientation >= 135)// 180
						{
							if (_orientation != ORIENTATION_PORTRAIT_INVERTED)
							{
								_orientation = ORIENTATION_PORTRAIT_INVERTED;
							}
						}
						else if (orientation < 135 && orientation > 45)// 90
						{
							if (_orientation != ORIENTATION_LANDSCAPE_INVERTED)
							{
								_orientation = ORIENTATION_LANDSCAPE_INVERTED;
							}
						}

					}

					if (lastOrientation != _orientation)
					{
						changeRotation(_orientation, lastOrientation);
					}
				}
			};
		}
		if (_orientationEventListener.canDetectOrientation())
		{
			_orientationEventListener.enable();
		}
	}

	@Override
	protected void onPause()
	{
		super.onPause();
		_orientationEventListener.disable();
	}

	@Override
	public void onWindowFocusChanged(boolean hasFocus)
	{		
		if(AppMain._codeResultService == CodeResult.FAIL_OPEN_CAMERA)
		{
			AppMain.showAlert(this, R.string.textErrorCameraFailOpen, true);
		}
		super.onWindowFocusChanged(hasFocus);
	}
	
	/**
	 * Performs required action to accommodate new orientation
	 * 
	 * @param orientation
	 * @param lastOrientation
	 */
	private void changeRotation(int orientation, int lastOrientation)
	{
		// switch (orientation)
		// {
		// case ORIENTATION_PORTRAIT_NORMAL:
		// mSnapButton.setImageDrawable(getRotatedImage(
		// android.R.drawable.ic_menu_camera, 270));
		// break;
		// case ORIENTATION_LANDSCAPE_NORMAL:
		// mSnapButton.setImageResource(android.R.drawable.ic_menu_camera);
		// Log.v("CameraActivity", "Orientation = 0");
		// break;
		// case ORIENTATION_PORTRAIT_INVERTED:
		// mSnapButton.setImageDrawable(getRotatedImage(
		// android.R.drawable.ic_menu_camera, 90));
		// break;
		// case ORIENTATION_LANDSCAPE_INVERTED:
		// mSnapButton.setImageDrawable(getRotatedImage(
		// android.R.drawable.ic_menu_camera, 180));
		// break;
		// }
	}

	/**
	 * Rotates given Drawable
	 * 
	 * @param drawableId
	 *            Drawable Id to rotate
	 * @param degrees
	 *            Rotate drawable by Degrees
	 * @return Rotated Drawable
	 */
	@SuppressWarnings("unused")
	private Drawable getRotatedImage(int drawableId, int degrees)
	{
		Bitmap original = BitmapFactory.decodeResource(getResources(), drawableId);
		Matrix matrix = new Matrix();
		matrix.postRotate(degrees);

		Bitmap rotated = Bitmap.createBitmap(original, 0, 0, original.getWidth(), original.getHeight(), matrix, true);
		return new BitmapDrawable(rotated);
	}

	@Override
	public void onBackPressed()
	{
		Intent intent = new Intent();
		setResult(RESULT_CANCELED, intent);
		finish();
		// super.onBackPressed();
	}
}
